#ifndef ___fat32_subtransaccion18_leer_datos_de_archivo

#define ___fat32_subtransaccion18_leer_datos_de_archivo 1

#include "f32_mto.c"

#include "f32_opAL.c"
#include "f32_opAM.c"
#include "f32_opAT.c"

struct fat32st18_datos {
  unsigned long clusterInicial;
  unsigned long posicionInicial;
  unsigned long cantidadDatos;
  unsigned long * cadena;
  unsigned long numeroBloque;
  unsigned long offsetBloque;
  char bloque[2048];
  void * datos;
  unsigned int conexion;
  unsigned long posicionActual;
  unsigned long cantidadRestante;
  unsigned long cantidadActual;
};

unsigned char fat32st_leer_datos_de_archivo(unsigned char, unsigned int, unsigned long, unsigned long, unsigned long, void **, unsigned char,
                                                                                                                                      void *);

unsigned char fat32st_leer_datos_de_archivo (unsigned char estado, unsigned int transaccion, unsigned long clusterInicial,
                                             unsigned long posicionInicial, unsigned long longitudLectura, void ** datos,
                                             unsigned char estadoOp, void * datosOp) {
  struct fat32st18_datos * datosST = *datos;
  switch (estado) {
  case 0:
    datosST = malloc(sizeof(fat32st18_datos));
    *datos = datosST;
    datosST -> clusterInicial = clusterInicial;
    datosST -> posicionInicial = posicionInicial;
    datosST -> cantidadDatos = longitudLectura;
    datosST -> datos = malloc(datosST -> cantidadDatos);
    datosST -> conexion = fat32_obtener_conexion_para_transaccion(transaccion);
    datosST -> numeroBloque = 0;
    fat32_crear_operacion(transaccion, &fat32op_obtener_cadena_clusteres, &(datosST -> clusterInicial), sizeof(datosST -> clusterInicial));
    return 1;
  case 1:
    datosST -> cadena = datosOp;
    fat32_quitar_operacion(transaccion);
    unsigned long cca;
    for (cca = 0; (datosST -> cadena)[cca]; cca ++);
    fat32_crear_operacion(transaccion, &fat32op_obtener_cadena_sectores_desde_clusteres, &(datosST -> cadena),
                                                                        sizeof(unsigned long int) * (cca + 1));
    return 2;
  case 2:
    free(datosST -> cadena);
    datosST -> cadena = datosOp;
    fat32_quitar_operacion(transaccion);
    datosST -> posicionActual = 0;
    return 3;
  case 3:
    if ((datosST -> posicionActual) >= (datosST -> cantidadDatos)) return 6;
    unsigned long dirSigSector = (datosST -> posicionInicial) + (datosST -> posicionActual);
    dirSigSector /= 512;
    unsigned long sectorActual = (datosST -> cadena)[dirSigSector];
    dirSigSector = (dirSigSector + 1) * 512;
    if (dirSigSector >= ((datosST -> posicionInicial) + (datosST -> cantidadDatos)))
      datosST -> cantidadActual = (datosST -> cantidadDatos) - (datosST -> posicionActual);
    else
      datosST -> cantidadActual = 512 - (((datosST -> posicionInicial) + (datosST -> posicionActual)) % 512);
    datosST -> offsetBloque = 512 * (sectorActual & 3) + (((datosST -> posicionInicial) + (datosST -> posicionActual)) % 512);
    unsigned long dirSigBloque = ((datosST -> cadena)[sectorActual]) & ~3L;
    if (dirSigBloque == (datosST -> numeroBloque)) return 5;
    struct fat32opAM_solicitud_bloque ds;
    ds.conexion = datosST -> conexion;
    ds.sector = datosST -> numeroBloque = dirSigBloque;
    ds.buffer = datosST -> bloque;
    fat32_crear_operacion(transaccion, &fat32op_solicitar_bloque, &ds, sizeof ds);
    return 4;
  case 4:
    fat32_quitar_operacion(transaccion);
    return 5;
  case 5:
    memcpy(((char *) (datosST -> datos)) + (datosST -> posicionActual), (datosST -> bloque) + (datosST -> offsetBloque),
                                                                                              datosST -> cantidadActual);
    datosST -> posicionActual += datosST -> cantidadActual;
    return 3;
  case 6:
    free(datosST -> cadena);
    *datos = datosST -> datos;
    free(datosST);
    return 0;
  }
}

#endif